import { Inject, Provide } from '@midwayjs/core';
import { BaseService } from '@cool-midway/core';
import { InjectEntityModel } from '@midwayjs/typeorm';
import { Repository, Between, Not, In, LessThan, MoreThan } from 'typeorm';
import { AppointmentInfoEntity } from '../entity/info';
import { CoolCommException } from '@cool-midway/core';
import { BaseSysUserEntity } from '../../base/entity/sys/user';
import { DictInfoEntity } from '../../dict/entity/info';
import { StudentStudentEntity } from '../../student/entity/student';
import { OrderInfoEntity } from '../../order/entity/info';
import { ClassInfoEntity } from '../../class/entity/info';
import { StudentPrescriptionEntity } from '../../student/entity/prescription';
import { exit } from 'process';
import { ProductProductEntity } from '../../product/entity/product';
import { AppointmentLimitEntity } from '../entity/limit';

/**
 * 预约信息
 */
@Provide()
export class AppointmentInfoService extends BaseService {
  @InjectEntityModel(AppointmentInfoEntity)
  appointmentInfoEntity: Repository<AppointmentInfoEntity>;

  @InjectEntityModel(BaseSysUserEntity)
  baseSysUserEntity: Repository<BaseSysUserEntity>;

  @InjectEntityModel(DictInfoEntity)
  dictInfoEntity: Repository<DictInfoEntity>;

  @InjectEntityModel(StudentStudentEntity)
  studentStudentEntity: Repository<StudentStudentEntity>;

  @InjectEntityModel(OrderInfoEntity)
  OrderInfoEntity: Repository<OrderInfoEntity>;

  @InjectEntityModel(ClassInfoEntity)
  classInfoEntity: Repository<ClassInfoEntity>;

  @InjectEntityModel(StudentPrescriptionEntity)
  studentPrescriptionEntity: Repository<StudentPrescriptionEntity>;

  @InjectEntityModel(ProductProductEntity)
  productProductEntity: Repository<ProductProductEntity>;

  @InjectEntityModel(AppointmentLimitEntity)
  appointmentLimitEntity: Repository<AppointmentLimitEntity>;

  @Inject()
  ctx;


  /**
   * 分页方法重写过滤数据
   */
  async page(query, options) {
    // 如果上传的appointmentTimeStartTime和appointmentTimeEndTime只有日期没有时间则给拼上时间，需要判断没有冒号
    if (query.appointmentTimeStartTime && query.appointmentTimeStartTime.indexOf(':') === -1) {
      query.appointmentTimeStartTime += ' 00:00:00';
    }
    if (query.appointmentTimeEndTime && query.appointmentTimeEndTime.indexOf(':') === -1) {
      query.appointmentTimeEndTime += ' 23:59:59';
    }
    if (query.appointmentStatus && query.appointmentStatus == 10086) {
      query.appointmentStatus = [0, 1];
    }
    const result = await super.page(query, options); // 先获取所有数据
    // 获取所有的学员
    const studentIds = result.list.map(item => item.studentId);
    // 查询学员数组
    const studentList = await this.studentStudentEntity.find({
      where: { id: In(studentIds) }
    });
    // 查询订单数组
    const orderList = await this.OrderInfoEntity.find({
      where: { userId: In(studentIds), status: 1 }
    });
    // 获取所有预约id
    const appointmentIds = result.list.map(item => item.id);

    // 查询处方数组
    const prescriptionList = await this.studentPrescriptionEntity.find({
      where: { appointmentId: In(appointmentIds) }
    });

    // 用户列表
    const salesArr = await this.baseSysUserEntity.find();

    // 获取每个学员的最新预约信息
    for (const student of result.list) {
      // 查询门店名称
      const sales = await this.baseSysUserEntity.findOne({
        where: { id: student.userSales }
      });
      student.userSalesName = sales ? sales.name : '';
      student.userAge = student.userBirthday ? new Date().getFullYear() - new Date(student.userBirthday).getFullYear() : 0;
      // 显示客户分层、依从性、入组、推荐方案的信息
      const studentObj = studentList.find(item => item.id == student.studentId);
      student.layer = studentObj.layer || '';
      student.compliance = studentObj.compliance || '';
      student.inGroup = studentObj.inGroup || '';
      student.suggestPlan = studentObj.suggestPlan || '';
      student.userType = studentObj.userType || '';
      student.decisionPerson = '';
      student.category = '';

      // 查找是否有预约id相关的处方
      const prescriptObj = prescriptionList.find(item => item.appointmentId == student.id);
      if (prescriptObj) {
        student.layer = prescriptObj.layer || '';
        student.compliance = prescriptObj.compliance || '';
        student.inGroup = prescriptObj.inGroup || '';
        student.suggestPlan = prescriptObj.suggestPlan || '';
        student.decisionPerson = prescriptObj.decisionPerson || '';
        student.category = prescriptObj.category || '';
        student.optometrist = prescriptObj.optometrist || '';
        // 查找验光师名称
        const optometrist = salesArr.find(item => item.id == prescriptObj.optometrist);
        student.optometristName = optometrist ? optometrist.name : '';
      }

      // 查询是否有支付的订单
      const order = orderList.find(item => item.userId == student.studentId);
      student.hasPay = order ? '已转化' : '-';
    }
    return result;
  }
  
  // 去重预约分页方法
  async page2(query, options) {

    const dictArr = await this.dictInfoEntity.find();
    // 获取分页参数
    const page = query.page || 1;
    const pageSize = query.pageSize || 20;
    const start = (page - 1) * pageSize;
    const end = start + Number(pageSize);
    // 1. 查询所有预约数据
    const allAppointments = await this.appointmentInfoEntity.find({
      order: { appointmentTime: 'DESC' } // 先按时间降序排序
    });

    // 2. 按学员id分组，保留最远预约时间的数据
    const uniqueAppointmentsMap = new Map<number, AppointmentInfoEntity>();

    for (const appointment of allAppointments) {
      const { studentId, appointmentTime } = appointment;
      
      if (!uniqueAppointmentsMap.has(studentId)) {
        // 如果学员id不存在于map中，直接添加
        uniqueAppointmentsMap.set(studentId, appointment);
      } else {
        // 如果已存在，比较预约时间，保留最远的
        const existingAppointment = uniqueAppointmentsMap.get(studentId);
        if (existingAppointment && new Date(appointmentTime) > new Date(existingAppointment.appointmentTime)) {
          uniqueAppointmentsMap.set(studentId, appointment);
        }
      }
    }

    // 3. 将map转换为数组
    let filteredList = Array.from(uniqueAppointmentsMap.values());
    // 得到的唯一去重数组再进行筛选
    // 如果上传的appointmentTimeStartTime和appointmentTimeEndTime只有日期没有时间则给拼上时间，需要判断没有冒号
    if (query.appointmentTimeStartTime && query.appointmentTimeStartTime.indexOf(':') === -1) {
      query.appointmentTimeStartTime += ' 00:00:00';
    }
    if (query.appointmentTimeEndTime && query.appointmentTimeEndTime.indexOf(':') === -1) {
      query.appointmentTimeEndTime += ' 23:59:59';
    }
    // 筛选数据
    filteredList = filteredList.filter(item => {
      const appointmentTime = new Date(item.appointmentTime);
      const startTime = new Date(query.appointmentTimeStartTime);
      const endTime = new Date(query.appointmentTimeEndTime);
      return appointmentTime >= startTime && appointmentTime <= endTime;
    });

    if (query.appointmentStatus) {
      filteredList = filteredList.filter(item => {
        return item.appointmentStatus == query.appointmentStatus;
      })
    }

    if (query.shopId) {
      filteredList = filteredList.filter(item => {
        return item.shopId == query.shopId;
      })
    }

    if (query.comeType) {
      filteredList = filteredList.filter(item => {
        return item.comeType == query.comeType;
      })
    }

    if (query.name) {
      const student = await this.studentStudentEntity.findOne({
        where: { name: query.name }
      });
      if (student) {
        filteredList = filteredList.filter(item => {
          return item.studentId == student.id;
        })
      } else {
        filteredList = [];
      }
    }

    if (query.phone) {
      const student = await this.studentStudentEntity.findOne({
        where: { phone: query.phone }
      });
      if (student) {
        filteredList = filteredList.filter(item => {
          return item.studentId == student.id;
        })
      } else {
        filteredList = [];
      }
    }



    const total = filteredList.length;
    // 4. 分页处理
    let paginatedList = [];
    if (query.isExport) {
      paginatedList = filteredList;
    } else {
      paginatedList = filteredList.slice(start, end);
    }
    // console.log('start end', start, end)
    // 选项
    const optionsArr = {
      appointmentStatus: [
        { label: '未到店', value: 0 },
        { label: '已到店', value: 1 },
        { label: '已改约', value: 2 },
        { label: '已过期', value: 3 },
        { label: '已取消', value: 4 },
      ],
      comeType: [
          { label: '未完成', value: 0 },
          { label: '完成', value: 2 },
      ],
      salesList: [],
      gender: [
        { label: '男', value: 0 },
        { label: '女', value: 1 },
        { label: '未知', value: 2 }
      ],
      appointmentType: [
        { label: '新客', value: 0 },
        { label: '复查', value: 1 }
      ],
      decisionPerson: [
        { label: '-', value: 0 },
        { label: '到场', value: 1 },
      ]
    };

    // 5. 补充学员信息等（与原page方法逻辑保持一致）
    // 获取所有的学员id
    const studentIds = paginatedList.map(item => item.studentId);
    // 查询学员数组
    const studentList = await this.studentStudentEntity.find({
      where: { id: In(studentIds) }
    });
    // 查询订单数组
    const orderList = await this.OrderInfoEntity.find({
      where: { userId: In(studentIds), status: 1 }
    });
    // 获取所有预约id
    const appointmentIds = paginatedList.map(item => item.id);
    // 查询处方数组
    const prescriptionList = await this.studentPrescriptionEntity.find({
      where: { appointmentId: In(appointmentIds) }
    });
    const salesArr = await this.baseSysUserEntity.find();
    // 完善预约信息
    let resultArr = [];
    for (const appointment of paginatedList) {
      // 重新构建数据
      let tempAppointment = {
        ...appointment,
        userGender: 0,
        userName: '',
        userPhone: '',
        userSalesName: '',
        userRemark: '',
        userAge: 0,
        layer: 0,
        layerName: '',
        compliance: 0,
        complianceName: '',
        inGroup: 0,
        inGroupName: '',
        suggestPlan: '',
        decisionPerson: 0,
        hasPay: '',
        userType: 0,
        category: 0,
        shopName: '',
        appointStatusName: '',
        distanceName: '',
        decisionPersonName: '',
        categoryName: '',
        appointTypeName: '',
        userGenderName: '',
      };


      // 查询门店名称
      
      
      // 显示客户分层、依从性、入组、推荐方案的信息
      const studentObj = studentList.find(item => item.id == appointment.studentId);
      tempAppointment.userSalesName = salesArr.find(item => item.id == studentObj.sales)?.name || '';
      tempAppointment.userAge = studentObj?.birthday ? new Date().getFullYear() - new Date(studentObj.birthday).getFullYear() : 0;
      tempAppointment.userGender = studentObj?.gender || 0;
      tempAppointment.userName = studentObj?.name || '';
      tempAppointment.userPhone = studentObj?.phone || '';
      tempAppointment.userRemark = studentObj?.remark || '';
      tempAppointment.layer = Number(studentObj?.layer || '');
      tempAppointment.compliance = Number(studentObj?.compliance || '');
      tempAppointment.inGroup = Number(studentObj?.inGroup || '');
      tempAppointment.suggestPlan = String(studentObj?.suggestPlan || '');
      tempAppointment.userType = Number(studentObj?.userType || '');
      // console.log('studentObj', studentObj, appointment.studentId)

      // 查找是否有预约id相关的处方
      const prescriptObj = prescriptionList.find(item => item.appointmentId == appointment.id);
      if (prescriptObj) {
        tempAppointment.layer = Number(prescriptObj.layer || '');
        tempAppointment.compliance = Number(prescriptObj.compliance || '');
        tempAppointment.inGroup = Number(prescriptObj.inGroup || '');
        tempAppointment.suggestPlan = String(prescriptObj.suggestPlan || '');
        tempAppointment.decisionPerson = Number(prescriptObj.decisionPerson || '');
        tempAppointment.category = Number(prescriptObj.category || '');
      }
      // 完善分层、依从性、入组的名称
      tempAppointment.layerName = dictArr.find(item => item.id == tempAppointment.layer)?.name || '';
      tempAppointment.complianceName = dictArr.find(item =>  item.id == tempAppointment.compliance)?.name || '';
      tempAppointment.inGroupName = dictArr.find(item => item.id == tempAppointment.inGroup)?.name || '';
      tempAppointment.shopName = dictArr.find(item => item.id == tempAppointment.shopId)?.name || '';
      tempAppointment.userTypeName = dictArr.find(item => item.id == tempAppointment.userType)?.name || '';
      tempAppointment.decisionPersonName = optionsArr.decisionPerson.find(item => item.value == tempAppointment.decisionPerson)?.label || '';
      tempAppointment.categoryName = dictArr.find(item => item.id == tempAppointment.category)?.name || '';


      tempAppointment.appointStatusName = optionsArr.appointmentStatus.find(item => item.value == tempAppointment.appointmentStatus)?.label || '';
      tempAppointment.userGenderName = optionsArr.gender.find(item => item.value == tempAppointment.userGender)?.label || '';
      tempAppointment.comeTypeName = optionsArr.comeType.find(item => item.value == tempAppointment.comeType)?.label || '';
      tempAppointment.appointTypeName = optionsArr.appointmentType.find(item => item.value == tempAppointment.appointmentType)?.label || '';



      // console.log('tempAppointment', tempAppointment, prescriptObj);
      // 查询是否有支付的订单
      const order = orderList.find(item => item.userId == appointment.studentId);
      tempAppointment.hasPay = order ? '已转化' : '-';
      resultArr.push(tempAppointment);
    }

    return {
      list: resultArr,
      pagination: {
        page: page,
        size: pageSize,
        total: total
      }
    };
  }


  /**
   * 已经到店
   */
  async appointCome(param: {
    appointId: number;
  }) {
    const appointInfo = await this.appointmentInfoEntity.findOne({
      where: {
        id: param.appointId,
      },
    });
    if (!appointInfo) {
      throw new CoolCommException('预约信息不存在');
    }
    appointInfo.appointmentStatus = appointInfo.appointmentStatus === 1 ? 0 : 1;
    appointInfo.updateTime = new Date();
    return await this.appointmentInfoEntity.save(appointInfo);
  }

  /**
   * 取消到店
   */
  async appointCancelCome(param: {
    appointId: number;
  }) {
    const appointInfo = await this.appointmentInfoEntity.findOne({
      where: {
        id: param.appointId,
      },
    });
    if (!appointInfo) {
      throw new CoolCommException('预约信息不存在');
    }
    // 假设取消到店后状态设为 0，可根据实际业务调整
    appointInfo.appointmentStatus = 0;
    appointInfo.updateTime = new Date();
    return await this.appointmentInfoEntity.save(appointInfo);
  }


  /**
   * 取消预约
   */
  async appointCancle(param: {
    appointId: number;
  }) {
    const appointInfo = await this.appointmentInfoEntity.findOne({
      where: {
        id: param.appointId,
      },
    });
    if (!appointInfo) {
      throw new CoolCommException('预约信息不存在');
    }
    appointInfo.appointmentStatus = 4;
    appointInfo.updateTime = new Date();
    return await this.appointmentInfoEntity.save(appointInfo);
  }

  /**
   * 预约
   * @param studentId
   * @param doctorId
   * @param shopId
   * @param date
   * @param time
   */
  async appoint(param: {
    studentId: number;    // 学生ID
    doctorId: number;     // 医生ID
    shopId: number;       // 门店ID
    date: string;  // 预约日期
    time: string;  // 预约时间
    ignoreConflict?: boolean; // 是否忽略冲突
  }) {
    // 检查是否有未来的预约
    const now = new Date();
    // const offset = now.getTimezoneOffset();
    const currentTime = new Date(now.getFullYear(), now.getMonth(), now.getDate());
    // console.log('currentTime', currentTime);
    const appointmentTime = new Date(`${param.date} ${param.time}`);
    // 验证预约时间是否已过
    if (appointmentTime < currentTime) {
      throw new CoolCommException('无法预约过去的时间');
    }
    // const appointmentTime = new Date(`${param.date} ${param.time}`);
    // 查询当天是否有预约限制
    let limits = await this.appointmentLimitEntity.find({
      where: {
        shopId: param.shopId,
        week: appointmentTime.getDay(),
        type: 0,
      }
    });
    // 查看当天是否有限制预约
    const todayLimit = await this.appointmentLimitEntity.find({
      where: {
        shopId: param.shopId,
        date: param.date,
        type: 1,
      }
    });
    if (todayLimit) {
      limits = todayLimit;
    }

    // 检查是否有历史预约
    const hasHistoryAppointment = await this.appointmentInfoEntity.findOne({
      where: {
        studentId: param.studentId,
        appointmentStatus: In([1, 5]),
      }
    });

    // 检查是不是门店账号
    let isShopAccount = false;
    // 查看roleIds是否不包含2和4
    if (this.ctx.admin.roleIds.includes(2) || this.ctx.admin.roleIds.includes(4)) {
      isShopAccount = true;
    }

    let noRules = false;
    if (isShopAccount && hasHistoryAppointment) {
      noRules = true;
    }
    console.log('noRules', noRules, isShopAccount, hasHistoryAppointment, this.ctx.admin.roleIds);

    if (limits.length > 0 && !noRules) {
      const appointmentStartTime = new Date(appointmentTime.getFullYear(), appointmentTime.getMonth(), appointmentTime.getDate(), 0, 0, 0);
      const appointmentEndTime = new Date(appointmentTime.getFullYear(), appointmentTime.getMonth(), appointmentTime.getDate(), 23, 0, 0);
      const count = await this.appointmentInfoEntity.count({
        where: {
          shopId: param.shopId,
          appointmentTime: Between(appointmentStartTime, appointmentEndTime),
          appointmentStatus: Not(In([2, 4]))  // 排除已取消的预约
        }
      });
      console.log(count, limits);
      if (count >= limits[0].limit) {
        throw new CoolCommException('该门店当天预约已满');
      }
      // 根据限制的时间，限制的时间也不可以预约
      if (limits[0].time) {
        const timeArr = limits[0].time.split(',');
        if (timeArr.includes(param.time)) {
          throw new CoolCommException('该时间段不可预约');
        }
      }
    }


    const existingAppointment = await this.appointmentInfoEntity.findOne({
      where: {
        studentId: param.studentId,
        appointmentTime: Between(currentTime, new Date('2099-12-31')),
        appointmentStatus: Not(In([1, 2, 4]))  // 排除已取消的预约
      }
    });


    // 检查该时间有几个预约
    
    const conflictAppointment = await this.appointmentInfoEntity.count({
      where: {
        shopId: param.shopId,
        // doctorId: param.doctorId,
        appointmentStatus: Not(In([2, 4])),
        appointmentTime: appointmentTime
      }
    });



    console.log(appointmentTime, conflictAppointment);
    if (conflictAppointment >= 1 && !param.ignoreConflict && !noRules) {
      throw new CoolCommException('该学员不是复查学员，不能重叠预约');
    }

    // 查询预约时间半小时内是否有班级在占用
    // const appointmentTimeNew = new Date(appointmentTime.getTime() + 1 * 1000);   // 多加1分钟判断冲突，允许在班级结束时间跟预约时间一致
    // const appointTimeEndNew = new Date(appointmentTime.getTime() + 29 * 60 * 1000);   // 少减一分钟，允许预约结束时间跟开始时间一致
    // const appointTimeEnd = new Date(appointmentTime.getTime() + 30 * 60 * 1000);   // 少减一分钟，允许预约结束时间跟开始时间一致
    // const conflictClass = await this.classInfoEntity.findOne({
    //   where: [
    //     {
    //       // 情况1：班级结束时间在预约时间范围内
    //       shopId: param.shopId,
    //       status: Not(0),
    //       startTime: LessThan(appointmentTime),
    //       endTime: Between(appointmentTimeNew, appointTimeEnd),
    //     },
    //     {
    //       // 情况2：班级开始时间在预约时间范围内
    //       shopId: param.shopId,
    //       status: Not(0),
    //       startTime: Between(appointmentTime, appointTimeEndNew)
    //     }
    //   ]
    // });

    // if (conflictClass && !param.ignoreConflict) {
    //   throw new CoolCommException('该时间段内有班级课程，请选择其他时间');
    // }

    

    const appointInfo = new AppointmentInfoEntity();
    appointInfo.studentId = param.studentId;
    appointInfo.doctorId = param.doctorId;
    appointInfo.shopId = param.shopId;
    appointInfo.appointmentTime = new Date(`${param.date} ${param.time}`);
    appointInfo.createTime = new Date();
    appointInfo.updateTime = new Date();
    appointInfo.appointmentType = hasHistoryAppointment ? 1 : 0;  // 如果有历史预约则设为复诊
    appointInfo.adminId = this.ctx.admin.userId;
    // 先保存新预约
    const savedAppointment = await this.appointmentInfoEntity.save(appointInfo);
    // 新预约保存成功后，取消旧预约
    if (savedAppointment && existingAppointment) {
      existingAppointment.appointmentStatus = 2;
      existingAppointment.updateTime = new Date();
      existingAppointment.cancleAdminId = this.ctx.admin.userId;
      await this.appointmentInfoEntity.save(existingAppointment);
    }
    // 如果新预约成功了且是公海的则修改销售和跟进状态
    const student = await this.studentStudentEntity.findOne({
      where: {
        id: param.studentId
      }
    });
    if (student && student.flowStatus == 131 && savedAppointment) {
      student.flowStatus = 134;
      student.sales = this.ctx.admin.userId;
      student.updateTime = new Date();
      await this.studentStudentEntity.save(student);
    }

    return await this.appointmentInfoEntity.save(appointInfo);
  }

  /**
   * 查看预约
   * @param studentId
   * @param doctorId
   * @param shopId
   * @param date
   */
  async dateAppoint(param: {
    shopId: number;       // 门店ID
    date: string;  // 预约日期
    doctorId: number;     // 医生ID
    endDate?: string;  // 结束日期
  }) {
    const startDate = new Date(`${param.date} 00:00:00`);
    const endDate = param.endDate 
      ? new Date(`${param.endDate} 23:59:59`)
      : new Date(`${param.date} 23:59:59`);
    // console.log('dateAppoint service', startDate, endDate);
    const appointInfo = await this.appointmentInfoEntity.find({
      select: ['id', 'appointmentTime', 'studentId', 'appointmentStatus', 'appointmentType'],
      where: {
        shopId: param.shopId,
        appointmentStatus: Not(In([2, 4])),
        appointmentTime: Between(startDate, endDate),
      },
    });

    // 获取所有相关学生的信息
    const studentIds = appointInfo.map(appoint => appoint.studentId);
    const students = await this.studentStudentEntity.find({
      select: ['id', 'name', 'project'],
      where: {
        id: In(studentIds)
      }
    });
    // 判断appointmentTime在11月19日后是否有1次出勤记录
    const attendanceRecords = await this.appointmentInfoEntity.find({
      where: {
        studentId: In(studentIds),
        appointmentStatus: 1,
        appointmentTime: MoreThan(new Date('2025-11-19 00:00:00')),
      }
    });

    // 提取每个学员出勤的最小日期
    const minAppointmentTimes = attendanceRecords.reduce((acc, record) => {
      if (!acc[record.studentId] || record.appointmentTime < acc[record.studentId]) {
        acc[record.studentId] = record.appointmentTime;
      }
      return acc;
    }, {} as Record<number, Date>);
    

    console.log(minAppointmentTimes);
    
    // 将学生信息添加到预约信息中
    const result = appointInfo.map(appoint => ({
      id: appoint.id,
      studentId: appoint.studentId,
      appointmentStatus: appoint.appointmentStatus,
      appointmentTime: appoint.appointmentTime,
      appointmentType: appoint.appointmentType,
      userName: students.find(student => student.id === appoint.studentId)?.name || '已预约',
      userSource: students.find(student => student.id === appoint.studentId)?.project || 0,
      // 红光招募只显示第一次出勤预约
      isShowHong: minAppointmentTimes[appoint.studentId] == null || minAppointmentTimes[appoint.studentId]?.getTime() >= appoint.appointmentTime.getTime() ? true : false,
      minAppointmentTimes: minAppointmentTimes[appoint.studentId]?.getTime(),
    }));

    return result;
  }

  /**
   * 查看所有预约信息和班级信息
   */
  async dateClass(param: {
    shopId: number;       // 门店ID
    date: string;  // 预约日期
    doctorId: number;     // 医生ID
    endDate?: string;  // 结束日期
  }) {
    const startDate = new Date(`${param.date} 00:00:00`);
    const endDate = param.endDate 
      ? new Date(`${param.endDate} 23:59:59`)
      : new Date(`${param.date} 23:59:59`);
    const classInfo = await this.classInfoEntity.find({
      where: {
        shopId: param.shopId,
        status: Not(0),
        startTime: Between(startDate, endDate)
      },
    });
    return classInfo;
  }

  /**
   * 预约行为看板
   */
  async appointSalesBoard(param: {
    startTime?: string; // 开始时间，可选
    endTime?: string;   // 结束时间，可选
  }) {
    // 处理时间范围
    let startDate = new Date();
    let endDate = new Date();
    if (param.startTime && param.endTime) {
      startDate = new Date(param.startTime);
      endDate = new Date(param.endTime);
    } else {
      startDate.setDate(startDate.getDate() - 6);
      startDate.setHours(0, 0, 0, 0);
      endDate.setHours(23, 59, 59, 999);
    }

    // 获取预约数据
    const appointments = await this.appointmentInfoEntity.find({
      where: {
        createTime: Between(startDate, endDate),
      },
      order: {
        studentId: 'ASC',
        appointmentStatus: 'ASC' // 状态升序，这样0和1会排在2前面
      }
    });

    // 获取所有相关销售信息
    const salesIds = [...new Set(appointments.map(s => s.adminId).filter(id => id))];
    const salesUsers = await this.baseSysUserEntity.find({
      where: {
        id: In(salesIds)
      }
    });

    // 定义销售统计数据的接口
    interface SalesStats {
      salesName: string;
      appointCount: number;
      cancelCount: number;
      validCount: number;
      processedStudents: Set<number>;
    }

    // 初始化销售统计数据
    const salesStats: Record<number, SalesStats> = {};
    for (const sales of salesUsers) {
      salesStats[sales.id] = {
        salesName: sales.name,
        appointCount: 0,
        cancelCount: 0,
        validCount: 0,
        processedStudents: new Set()
      };
    }

    // 处理预约数据
    for (const appointment of appointments) {
      if (salesStats[appointment.adminId]) {
        const salesData = salesStats[appointment.adminId];
        
        // 如果学生已经处理过，跳过
        if (salesData.processedStudents.has(appointment.studentId)) {
          continue;
        }

        // 记录学生已处理
        salesData.processedStudents.add(appointment.studentId);

        // 根据预约状态统计
        if (appointment.appointmentStatus === 2 || appointment.appointmentStatus === 4) {
          salesData.cancelCount++;
        } else {
          salesData.appointCount++;
        }
      }
    }

    // 转换为数组格式并计算有效数
    const result = Object.values(salesStats).map((stats: SalesStats) => ({
      salesName: stats.salesName,
      appointCount: stats.appointCount,
      cancelCount: stats.cancelCount,
      validCount: stats.appointCount - stats.cancelCount
    }));

    return result;
  }

  /**
   * 预约到店转化看板
   */
  async shopConvertPerformance(param: {
    shopId: number; // 门店ID
    channelId: number;  // 渠道ID
    startTime?: string; // 开始时间，可选
    endTime?: string;   // 结束时间，可选
    appointmentType?: string;  // 预约类型
  }) {
    // 初始化结果数组
    const result = [];

    // 获取门店ID和名称
    const shopArr = await this.dictInfoEntity.find({
      where: {
        typeId: 27,
        ...(param.shopId ? { id: Number(param.shopId) } : {})
      }
    });

    shopArr.sort((a, b) => a.orderNum - b.orderNum);

    // 处理时间范围
    let startDate = new Date();
    let endDate = new Date();
    
    if (param.startTime && param.endTime) {
      // 如果提供了时间范围，使用提供的时间
      startDate = new Date(param.startTime);
      endDate = new Date(param.endTime);
      endDate.setHours(23, 59, 59, 999);
    } else {
      // 默认最近7天
      startDate.setDate(startDate.getDate() - 6); // 减6天得到最近7天
      startDate.setHours(0, 0, 0, 0);
      endDate.setHours(23, 59, 59, 999);
    }

    // 为每个门店创建合计行数据对象
    for (const shop of shopArr) {
      result.push({
        shopName: shop.name,
        shopId: shop.id,
        date: '合计',
        appoint: 0,
        sign_first: 0,
        sign_second: 0,
        sign_total: 0,
        buy_first: 0,
        buy_second: 0,
        buy_total: 0,
        money_first: 0,
        money_second: 0,
        money_total: 0,
        sign_rate: 0,
        sign_first_rate: 0,
        sign_second_rate: 0,
        conversion_first_rate: 0,
        conversion_second_rate: 0,
        conversion_total_rate: 0,
        customer_first_price: 0,
        customer_second_price: 0,
        customer_total_price: 0
      });
    }

    // 获取预约数据
    const appointments = await this.appointmentInfoEntity.find({
      where: {
        appointmentTime: Between(startDate, endDate),
        ...(param.shopId ? { shopId: Number(param.shopId) } : {}),
        appointmentStatus: Not(In([2, 4])), // 排除已取消的预约
        appointmentType: param.appointmentType === '0,1' ? In([0, 1]) : Number(param.appointmentType),
      }
    });

    // 如果有channelId参数，先获取学生信息
    let filteredAppointments = appointments;
    if (param.channelId) {
      // 获取所有相关学生信息
      const studentIds = appointments.map(a => a.studentId);
      const students = await this.studentStudentEntity.find({
        where: {
          id: In(studentIds),
          source: param.channelId
        }
      });

      // 过滤出符合渠道条件的预约
      const validStudentIds = students.map(s => s.id);
      filteredAppointments = appointments.filter(appointment => 
        validStudentIds.includes(appointment.studentId)
      );
    }
    
    // 对预约的studentId进行去重处理 - 确保同一学生多次预约只算一次
    const uniqueStudentAppointments: Record<number, any> = {};
    for (const appointment of filteredAppointments) {
      const key = appointment.studentId;
      if (!uniqueStudentAppointments[key]) {
        uniqueStudentAppointments[key] = appointment;
      }
    }
    const distinctAppointments = Object.values(uniqueStudentAppointments);
    
    
    // 获取日期范围内的所有订单信息
    const orders = await this.OrderInfoEntity.find({
      where: {
        createTime: Between(startDate, endDate),
        ...(param.shopId ? { shopId: Number(param.shopId) } : {}),
        status: 1  // 已支付的订单
      }
    });

    // 获取有效商品的Ids
    const products = await this.productProductEntity.find({
      where: {
        convertType: 1
      }
    });
    const productIds = products.map(p => p.id);
    // 过滤出订单中包含有效商品的订单
    const filteredOrders = orders.filter(order => {
      return order.ProductIds.some(detail => productIds.includes(detail));
    });

    // 如果有channelId参数，先获取学生信息
    let filterOrders = filteredOrders;
    if (param.channelId) {
      // 获取所有相关学生信息
      const studentIds = orders.map(a => a.userId);
      const students = await this.studentStudentEntity.find({
        where: {
          id: In(studentIds),
          source: param.channelId
        }
      });

      // 过滤出符合渠道条件的预约
      const validStudentIds = students.map(s => s.id);
      filterOrders = orders.filter(order => 
        validStudentIds.includes(order.userId)
      );
    }

    // 按 userId 合并订单（不再按日期）
    const mergedOrders: Record<string, { payAmount: number; createTime: Date; userId: number, shopId: number }> = {};
    for (const order of filterOrders) {
      const key = `${order.userId}`; // 只按用户ID合并
      if (!mergedOrders[key]) {
        mergedOrders[key] = {
          payAmount: 0,
          createTime: order.createTime,
          userId: order.userId,
          shopId: order.shopId
        };
      }
      mergedOrders[key].payAmount += Number(order.payAmount || 0);
    }
    const uniqueOrders = Object.values(mergedOrders);

    // 直接处理预约数据到合计行 - 使用去重后的预约数据
    for (const appointment of distinctAppointments) {
      const totalRow = result.find(d => d.shopId === appointment.shopId && d.date === '合计');
      
      if (totalRow) {
        // 增加门店名称和ID
        totalRow.shopName = shopArr.find(s => s.id === appointment.shopId)?.name || '';
        totalRow.shopId = appointment.shopId;

        // 增加预约总数
        totalRow.appoint++;

        // 处理到店数据
        if (appointment.appointmentStatus === 1 || appointment.appointmentStatus === 5) {
          if (appointment.appointmentType === 0) {
            totalRow.sign_first++;
          } else {
            totalRow.sign_second++;
          }
          totalRow.sign_total++;
        }
      }
    }

    // 直接处理订单数据到合计行 - 订单已经按用户去重且金额合计
    for (const order of uniqueOrders) {
      const totalRow = result.find(d => d.shopId === order.shopId && d.date === '合计');
      
      if (totalRow) {
        // 获取该用户的历史预约记录，判断是否为首诊
        const hasHistoryAppointment = await this.appointmentInfoEntity.findOne({
          where: {
            studentId: order.userId,
            appointmentStatus: 1,
            appointmentType: 1,
            appointmentTime: LessThan(order.createTime)
          }
        });
        if (param.appointmentType === '0,1') {
          
        }
        // 只看新客
        else if (Number(param.appointmentType) === 0 && hasHistoryAppointment) {
          continue;
        }
        // 只看复诊
        else if (Number(param.appointmentType) === 1 && !hasHistoryAppointment) {
          continue;
        }
        
        
        // 根据是否有历史预约来统计首诊/复诊数据
        if (!hasHistoryAppointment) {
          // 首诊
          totalRow.buy_first++;
          totalRow.money_first += Number(order.payAmount || 0);
        } else {
          if (hasHistoryAppointment.appointmentType === 0) {
            // 首诊
            totalRow.buy_first++;
            totalRow.money_first += Number(order.payAmount || 0);
          } else {
            // 复诊
            totalRow.buy_second++;
            totalRow.money_second += Number(order.payAmount || 0);
          }
        }
        totalRow.buy_total++;
        totalRow.money_total = totalRow.money_first + totalRow.money_second;
      }
    }

    // 计算合计行的各种率
    for (const totalRow of result) {
      // 计算到店率
      totalRow.sign_rate = totalRow.appoint > 0 ? Number((totalRow.sign_total / totalRow.appoint * 100).toFixed(2)) : 0;
      totalRow.sign_first_rate = totalRow.appoint > 0 ? Number((totalRow.sign_first / totalRow.appoint * 100).toFixed(2)) : 0;
      totalRow.sign_second_rate = totalRow.appoint > 0 ? Number((totalRow.sign_second / totalRow.appoint * 100).toFixed(2)) : 0;
      
      // 计算转化率
      totalRow.conversion_first_rate = totalRow.sign_first > 0 ? Number((totalRow.buy_first / totalRow.sign_first * 100).toFixed(2)) : 0;
      totalRow.conversion_second_rate = totalRow.sign_second > 0 ? Number((totalRow.buy_second / totalRow.sign_second * 100).toFixed(2)) : 0;
      totalRow.conversion_total_rate = totalRow.sign_total > 0 ? Number((totalRow.buy_total / totalRow.sign_total * 100).toFixed(2)) : 0;

      // 计算客单价
      totalRow.customer_first_price = totalRow.buy_first > 0 ? Math.round(totalRow.money_first / totalRow.buy_first) : 0;
      totalRow.customer_second_price = totalRow.buy_second > 0 ? Math.round(totalRow.money_second / totalRow.buy_second) : 0;
      totalRow.customer_total_price = totalRow.buy_total > 0 ? Math.round(totalRow.money_total / totalRow.buy_total) : 0;
    }

    // 返回结果（已经只有合计行）
    return result;
  }

  /**
   * 预约到店转化数据看板
   * @param param
   */
  async appointBoard(param: {
    shopId: number; // 门店ID
    channelId: number;  // 渠道ID
    startTime?: string; // 开始时间，可选
    endTime?: string;   // 结束时间，可选
    appointmentType?: string;  // 预约类型
  }) {
    // 初始化结果数组
    const result = [];

    // 获取门店ID和名称
    const shopArr = await this.dictInfoEntity.find({
      where: {
        typeId: 27,
        ...(param.shopId ? { id: Number(param.shopId) } : {})
      }
    });

    shopArr.sort((a, b) => a.orderNum - b.orderNum);

    // 处理时间范围
    let startDate = new Date();
    let endDate = new Date();
    
    if (param.startTime && param.endTime) {
      // 如果提供了时间范围，使用提供的时间
      startDate = new Date(param.startTime);
      endDate = new Date(param.endTime);
      endDate.setHours(23, 59, 59, 999);
    } else {
      // 默认最近7天
      startDate.setDate(startDate.getDate() - 6); // 减6天得到最近7天
      startDate.setHours(0, 0, 0, 0);
      endDate.setHours(23, 59, 59, 999);
    }

    // 生成降序日期数组
    const dates = [];
    let currentDate = new Date(endDate);
    while (currentDate >= startDate) {
      dates.push(new Date(currentDate));
      currentDate.setDate(currentDate.getDate() - 1);
    }
    
    // 为每个门店和日期创建数据对象
    for (const shop of shopArr) {
      for (const date of dates) {
        const dateStr = date.toISOString().split('T')[0];
        // 为每个门店创建一条记录
        result.push({
          shopName: shop.name,
          shopId: shop.id,
          date: dateStr,
          appoint: 0,
          sign_first: 0,
          sign_second: 0,
          sign_total: 0,
          buy_first: 0,
          buy_second: 0,
          buy_total: 0,
          money_first: 0,
          money_second: 0,
          money_total: 0,
          sign_rate: 0,
          sign_first_rate: 0,
          sign_second_rate: 0,
          conversion_first_rate: 0,
          conversion_second_rate: 0,
          conversion_total_rate: 0,
          customer_first_price: 0,
          customer_second_price: 0,
          customer_total_price: 0
        });
      }
      // 添加该店铺的合计行
      result.push({
        shopName: shop.name,
        shopId: shop.id,
        date: '合计',
        appoint: 0,
        sign_first: 0,
        sign_second: 0,
        sign_total: 0,
        buy_first: 0,
        buy_second: 0,
        buy_total: 0,
        money_first: 0,
        money_second: 0,
        money_total: 0,
        sign_rate: 0,
        sign_first_rate: 0,
        sign_second_rate: 0,
        conversion_first_rate: 0,
        conversion_second_rate: 0,
        conversion_total_rate: 0,
        customer_first_price: 0,
        customer_second_price: 0,
        customer_total_price: 0
      });
    }

    // 获取预约数据
    const appointments = await this.appointmentInfoEntity.find({
      where: {
        appointmentTime: Between(startDate, endDate),
        ...(param.shopId ? { shopId: Number(param.shopId) } : {}),
        appointmentStatus: Not(In([2, 4])), // 排除已取消的预约
        appointmentType: param.appointmentType === '0,1' ? In([0, 1]) : Number(param.appointmentType),
      }
    });

    // 如果有channelId参数，先获取学生信息
    let filteredAppointments = appointments;
    if (param.channelId) {
      // 获取所有相关学生信息
      const studentIds = appointments.map(a => a.studentId);
      const students = await this.studentStudentEntity.find({
        where: {
          id: In(studentIds),
          source: param.channelId
        }
      });

      // 过滤出符合渠道条件的预约
      const validStudentIds = students.map(s => s.id);
      filteredAppointments = appointments.filter(appointment => 
        validStudentIds.includes(appointment.studentId)
      );
    }
    
    
    // 获取日期范围内的所有订单信息
    const orders = await this.OrderInfoEntity.find({
      where: {
        createTime: Between(startDate, endDate),
        ...(param.shopId ? { shopId: Number(param.shopId) } : {}),
        status: 1  // 已支付的订单
      }
    });

    // 获取有效商品的Ids
    const products = await this.productProductEntity.find({
      where: {
        convertType: 1
      }
    });
    const productIds = products.map(p => p.id);
    // 过滤出订单中包含有效商品的订单
    const filteredOrders = orders.filter(order => {
      return order.ProductIds.some(detail => productIds.includes(detail));
    });

    // 如果有channelId参数，先获取学生信息
    let filterOrders = filteredOrders;
    if (param.channelId) {
      // 获取所有相关学生信息
      const studentIds = orders.map(a => a.userId);
      const students = await this.studentStudentEntity.find({
        where: {
          id: In(studentIds),
          source: param.channelId
        }
      });

      // 过滤出符合渠道条件的预约
      const validStudentIds = students.map(s => s.id);
      filterOrders = orders.filter(order => 
        validStudentIds.includes(order.userId)
      );
    }

    // 按 userId 和日期合并订单
    const mergedOrders: Record<string, { payAmount: number; createTime: Date; userId: number, shopId: number }> = {};
    for (const order of filterOrders) {
      const orderDate = new Date(order.createTime).toISOString().split('T')[0];
      const key = `${order.userId}-${orderDate}`;
      if (!mergedOrders[key]) {
        mergedOrders[key] = {
          payAmount: 0,
          createTime: order.createTime,
          userId: order.userId,
          shopId: order.shopId
        };
      }
      mergedOrders[key].payAmount += Number(order.payAmount || 0);
    }
    const uniqueOrders = Object.values(mergedOrders);

    // 处理每个预约数据
    for (const appointment of filteredAppointments) {
      const appointDate = appointment.appointmentTime.toISOString().split('T')[0];
      const dayData = result.find(d => 
        d.date === appointDate && 
        d.shopId === appointment.shopId
      );
      
      if (dayData) {
        // 增加门店名称和ID
        dayData.shopName = shopArr.find(s => s.id === appointment.shopId)?.name || '';
        dayData.shopId = appointment.shopId;

        // 增加预约总数
        dayData.appoint++;

        // 处理到店数据
        if (appointment.appointmentStatus === 1 || appointment.appointmentStatus === 5) {
          if (appointment.appointmentType === 0) {
            dayData.sign_first++;
          } else {
            dayData.sign_second++;
          }
          dayData.sign_total++;
        }

        // 计算到店率
        dayData.sign_rate = dayData.appoint > 0 ? Number((dayData.sign_total / dayData.appoint * 100).toFixed(2)) : 0;
        dayData.sign_first_rate = dayData.appoint > 0 ? Number((dayData.sign_first / dayData.appoint * 100).toFixed(2)) : 0;
        dayData.sign_second_rate = dayData.appoint > 0 ? Number((dayData.sign_second / dayData.appoint * 100).toFixed(2)) : 0;
      }
    }

    // 独立处理订单数据
    for (const order of uniqueOrders) {
      // 将字符串日期转换为 Date 对象
      const orderDate = new Date(order.createTime).toISOString().split('T')[0];
      const dayData = result.find(d => 
        d.date === orderDate && 
        d.shopId === order.shopId
      );
      
      if (dayData) {
        // 增加门店名称和ID
        dayData.shopName = shopArr.find(s => s.id === order.shopId)?.name || '';
        dayData.shopId = order.shopId;

        // 获取该用户的历史预约记录，判断是否为首诊
        const hasHistoryAppointment = await this.appointmentInfoEntity.findOne({
          where: {
            studentId: order.userId,
            appointmentStatus: 1,
            appointmentType: 1,
            appointmentTime: LessThan(order.createTime)
          }
        });
        if (param.appointmentType === '0,1') {
          
        }
        // 只看新客
        else if (Number(param.appointmentType) === 0 && hasHistoryAppointment) {
          continue;
        }
        // 只看复诊
        else if (Number(param.appointmentType) === 1 && !hasHistoryAppointment) {
          continue;
        }
        
        
        // 根据是否有历史预约来统计首诊/复诊数据
        if (!hasHistoryAppointment) {
          // 首诊
          dayData.buy_first++;
          dayData.money_first += Number(order.payAmount || 0);
        } else {
          if (hasHistoryAppointment.appointmentType === 0) {
            // 首诊
            dayData.buy_first++;
            dayData.money_first += Number(order.payAmount || 0);
          } else {
            // 复诊
            dayData.buy_second++;
            dayData.money_second += Number(order.payAmount || 0);
          }
        }
        dayData.buy_total++;
        dayData.money_total = dayData.money_first + dayData.money_second;

        // 计算转化率
        dayData.conversion_first_rate = dayData.sign_first > 0 ? Number((dayData.buy_first / dayData.sign_first * 100).toFixed(2)) : 0;
        dayData.conversion_second_rate = dayData.sign_second > 0 ? Number((dayData.buy_second / dayData.sign_second * 100).toFixed(2)) : 0;
        dayData.conversion_total_rate = dayData.sign_total > 0 ? Number((dayData.buy_total / dayData.sign_total * 100).toFixed(2)) : 0;

        // 计算客单价
        dayData.customer_first_price = dayData.buy_first > 0 ? Math.round(dayData.money_first / dayData.buy_first) : 0;
        dayData.customer_second_price = dayData.buy_second > 0 ? Math.round(dayData.money_second / dayData.buy_second) : 0;
        dayData.customer_total_price = dayData.buy_total > 0 ? Math.round(dayData.money_total / dayData.buy_total) : 0;
      }
    }

    // 处理每个预约数据后，更新合计行
    for (const shop of shopArr) {
      // 获取该店铺的所有数据行（不包括合计行）
      const shopData = result.filter(d => d.shopId === shop.id && d.date !== '合计');
      // 获取该店铺的合计行
      const totalRow = result.find(d => d.shopId === shop.id && d.date === '合计');
      
      if (totalRow) {
        // 计算合计数据
        shopData.forEach(dayData => {
          totalRow.appoint += dayData.appoint;
          totalRow.sign_first += dayData.sign_first;
          totalRow.sign_second += dayData.sign_second;
          totalRow.sign_total += dayData.sign_total;
          totalRow.buy_first += dayData.buy_first;
          totalRow.buy_second += dayData.buy_second;
          totalRow.buy_total += dayData.buy_total;
          totalRow.money_first += dayData.money_first;
          totalRow.money_second += dayData.money_second;
          totalRow.money_total += dayData.money_total;
        });

        // 计算合计行的各种率
        totalRow.sign_rate = totalRow.appoint > 0 ? Number((totalRow.sign_total / totalRow.appoint * 100).toFixed(2)) : 0;
        totalRow.sign_first_rate = totalRow.appoint > 0 ? Number((totalRow.sign_first / totalRow.appoint * 100).toFixed(2)) : 0;
        totalRow.sign_second_rate = totalRow.appoint > 0 ? Number((totalRow.sign_second / totalRow.appoint * 100).toFixed(2)) : 0;
        
        totalRow.conversion_first_rate = totalRow.sign_first > 0 ? Number((totalRow.buy_first / totalRow.sign_first * 100).toFixed(2)) : 0;
        totalRow.conversion_second_rate = totalRow.sign_second > 0 ? Number((totalRow.buy_second / totalRow.sign_second * 100).toFixed(2)) : 0;
        totalRow.conversion_total_rate = totalRow.sign_total > 0 ? Number((totalRow.buy_total / totalRow.sign_total * 100).toFixed(2)) : 0;

        totalRow.customer_first_price = totalRow.buy_first > 0 ? Math.round(totalRow.money_first / totalRow.buy_first) : 0;
        totalRow.customer_second_price = totalRow.buy_second > 0 ? Math.round(totalRow.money_second / totalRow.buy_second) : 0;
        totalRow.customer_total_price = totalRow.buy_total > 0 ? Math.round(totalRow.money_total / totalRow.buy_total) : 0;
      }
    }

    return result;
    
  }

  
  async board(param: { visitType: string, startTime: string; endTime: string }) {
    const sources = await this.dictInfoEntity.find({
      where: {
        typeId: 26
      },
      select: ['id', 'name']
    });
    // 添加一个固定的记录
    const defaultSource = new DictInfoEntity();
    defaultSource.id = 0;
    defaultSource.name = '其他';
    sources.unshift(defaultSource);
    const dictIds = sources.map(item => item.id);
    
    // 获取所有门店
    const shops = await this.dictInfoEntity.find({
      where: {
        typeId: 27
      },
    });
    // 获取历史预约记录的学生ID
    const historicalStudentIds = new Set<number>();
    if (param.visitType === 'review' || param.visitType === 'first') {
      const historicalAppointments = await this.appointmentInfoEntity.find({
        select: ['studentId'],
        where: {
          appointmentStatus: In([0, 1, 3]),
          appointmentTime: LessThan(new Date(`${param.startTime} 00:00:00`))
        }
      });
      
      historicalAppointments.forEach(appointment => {
        historicalStudentIds.add(appointment.studentId);
      });
    }

    // 获取所有有效预约
    const appointments = await this.appointmentInfoEntity.find({
      where: {
        appointmentStatus: In([0, 1, 3]),
        appointmentTime: Between(
          new Date(`${param.startTime} 00:00:00`),
          new Date(`${param.endTime} 23:59:59`)
        ),
        ...(param.visitType === 'review' 
          ? { studentId: In([...historicalStudentIds]) }
          : param.visitType === 'first'
          ? { studentId: Not(In([...historicalStudentIds])) }
          : {})
      }
    });

    /// 获取所有相关学生信息
    const studentIds = appointments.map(a => a.studentId);
    const students = await this.studentStudentEntity.find({
      where: {
        id: In(studentIds)
      }
    });

    // 初始化结果数组
    const result = shops.map(shop => {
      const row = { shop: shop.name };
      dictIds.forEach(id => {
        row[id] = 0;
      });
      row['total'] = 0; // 添加每个店铺的合计列
      return row;
    });

    // 添加一个合计行
    const totalRow = { shop: '合计' };
    dictIds.forEach(id => {
      totalRow[id] = 0;
    });
    totalRow['total'] = 0;

    let count = 0;
    // 统计数据
    for (const appointment of appointments) {
      const shopIndex = result.findIndex(r => r.shop === shops.find(s => s.id === appointment.shopId)?.name);
      const student = students.find(s => s.id === appointment.studentId);
      if (shopIndex > -1 && student?.source !== undefined && student?.source !== null) {
        if (dictIds.includes(student.source)) {
          result[shopIndex][student.source]++;
          result[shopIndex]['total']++; // 增加店铺行合计
          totalRow[student.source]++; // 增加来源列合计
          totalRow['total']++; // 增加总计
          count++;
        }
      }
    }

    result.push(totalRow); // 添加合计行

    return {
      columnNames: [
        ...sources.map(item => ({
          id: item.id,
          name: item.name
        })),
        { id: 'total', name: '合计' } // 添加合计列
      ],
      list: result,
    }
  }

  /**
   * 每日任务：将昨天的已预约数据改为已过期
   */
  async updateAppointmentStatus() {
    // 获取昨天的日期，并设置为23:59:59
    const yesterday = new Date();
    // yesterday.setDate(yesterday.getDate() - 1);
    
    // 使用字符串方式设置时间
    // 设置为当地时间的23:59:59
    const year = yesterday.getFullYear();
    const month = String(yesterday.getMonth() + 1).padStart(2, '0');
    const date = String(yesterday.getDate()).padStart(2, '0');
    const localYesterday = `${year}-${month}-${date} 23:59:59`;

    // console.log('updateAppointmentStatus', localYesterday, new Date(localYesterday));

    // 查找所有过期未到店的预约
    const expiredAppointments = await this.appointmentInfoEntity.find({
      where: {
        appointmentStatus: 0,  // 未到店
        appointmentTime: LessThan(new Date(localYesterday))
      }
    });

    // 批量更新状态为已取消
    if (expiredAppointments.length > 0) {
      await this.appointmentInfoEntity.update(
        expiredAppointments.map(appointment => appointment.id),
        {
          appointmentStatus: 3,  // 已取消
          updateTime: new Date()
        }
      );
    }

    return {
      success: true,
      count: expiredAppointments.length
    };
  }

  async update(param) {
    if (param.appointmentStatus === 5) {
      param.appointmentStatus = 1;
      param.comeType = 2;
    }
    return await this.appointmentInfoEntity.save(param);
  }

  // 限制门店星期的预约人数
  async updateShopWeekLimit(param) {
    // 查看是否已经有限制
    let limit = await this.appointmentLimitEntity.findOne({
      where: {
        shopId: param.shopId,
        week: param.week,
        type: param.type || 0,// 默认是周类型，如果是1则是天类型
      }
    });
    if (param.type == 1) {
      limit = await this.appointmentLimitEntity.findOne({
        where: {
          shopId: param.shopId,
          week: param.week,
          type: param.type || 0,// 默认是周类型，如果是1则是天类型
          date: param.date,
        }
      });
    }
    if (limit) {
      param.id = limit.id;
    }
    if (param.limit === null) {
      param.limit = 50;
    }
    param.operatorId = this.ctx.admin.userId;
    return await this.appointmentLimitEntity.save(param);
  }

  // 根据门店获取限制的星期数组
  async getShopWeekLimit(shopId) {
    const limits = await this.appointmentLimitEntity.find({
      where: {
        shopId,
      }
    });
    return limits;
  }

  // 根据门店id，日期id，类型获取限制
  async getShopDateLimit(shopId: number, week?: number, date?: string, type?: number) {
    let limit = null;
    if (week) {
      limit = await this.appointmentLimitEntity.findOne({
        where: {
          shopId,
          week,
          type,
        }
      });
    }
    if (date) {
      limit = await this.appointmentLimitEntity.findOne({
        where: {
          shopId,
          date,
          type,
        }
      });
    }
    if (limit) {
      return limit;
    }
    throw new CoolCommException('暂无设置');
  }
}
